﻿using BleSolution;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace YH.Bluetooth
{
    public class UtilClass
    {
        private static readonly int[] HeadRange = { 0, 4 };
        private static readonly int[] PacketLengthRange = { 4, 6 };
        private static readonly int[] LtRange = { 6, 8 };
        private static readonly int[] Eeg0Ranges = { 8, 14 };
        private static readonly int[] Eeg1Ranges = { 14, 20 };
        private static readonly int[] Eeg2Ranges = { 20, 26 };
        private static readonly int[] Eeg3Ranges = { 26, 32 };
        private static readonly int[] Eeg4Ranges = { 32, 38 };
        private static readonly int[] KwhRange = { 38, 40 };
        private static readonly int[] RechargeStatusRange = { 40, 42 };
        private const string LtInvalidData = "00"; // 无效数据标识
        private const string HeadData = "7e01"; // 消息头
        public static DeviceData GetDeviceData(byte[] byteArray) 
        {
            DeviceData deviceData = new DeviceData
            {
                EegList = new List<float>(), // 存储EEG数据
                AccList = new List<float>(), // 存储加速度数据
                GyrList = new List<float>()  // 存储角速度数据
            };
            try
            {
                // 将byteArray转为sbyte数组，以便正确处理有符号字节，并去掉第一个元素
                sbyte[] data = byteArray.Skip(1).Select(b => (sbyte)(b > 127 ? b - 256 : b)).ToArray();
                // 提取EEG数据
                for (int i = 0; i < 13; i += 3)
                {
                    float value = Extract3BitData(data, i); // 提取3位数据
                    float tempEeg = value * GetEegType();   // 根据设备类型获取EEG值
                    deviceData.EegList.Add(tempEeg);        // 将EEG值添加到列表中
                }

                sbyte IMU_check = data[17]; // 检查IMU状态（因为data是从byteArray.slice(1)开始的）
                if (IMU_check != 0 && byteArray.Length >= 29) // 确保有足够的数据来读取IMU
                {
                    List<float> temIMUArray = new List<float>();

                    // 提取IMU数据
                    for (int j = 18; j < 29; j += 2) // 注意这里调整了起始索引和结束条件
                    {
                        float value1 = Extract2BitData(data, j); // 提取2位数据

                        float tempIMU = j < 24 ? GetAcc(value1) : GetGyr(value1); // 根据索引判断是加速度还是角速度
                        temIMUArray.Add(tempIMU); // 添加到IMU数组
                    }
                    deviceData.AccList.AddRange(GetImu(temIMUArray.Take(3).ToList(), 1)); // 获取前3个加速度值
                    deviceData.GyrList.AddRange(GetImu(temIMUArray.Skip(3).Take(3).ToList(), 2)); // 获取后3个角速度值
                }
                return deviceData; // 返回设备数据
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex);
                return deviceData;
            }
        }
        private static float Extract3BitData(sbyte[] mySbyte, int off)
        {
            try
            {
                byte b0 = (byte)mySbyte[off];
                byte b1 = (byte)mySbyte[off + 1];
                byte b2 = (byte)mySbyte[off + 2];

                uint combinedValue = ((uint)b0 << 16) | ((uint)b1 << 8) | (uint)b2;
                return (float)combinedValue;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex);
                return 0.0f;
            }
           
        }
        private static float GetEegType()
        {
            // 根据设备类型获取EEG参考值
            float refEEG = 0.0198682f; // 其他类型的参考值
            return refEEG; // 返回参考值
        }

        private static float Extract2BitData(sbyte[] mySbyte, int off)
        {
            try
            {
                sbyte b0 = mySbyte[off];
                sbyte b1 = mySbyte[off + 1];

                // 将两个字节组合成一个16位的无符号整数
                ushort combinedValue = (ushort)(((b0 & 0xFF) << 8) | (b1 & 0xFF));

                // 假设16位整数直接映射到float，具体转换逻辑取决于实际应用需求
                // 下面的例子简单地将16位整数除以一个适当的因子来获得浮点数
                return (float)combinedValue;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex);
                return 0.0f;
            }
           
        }
        private static float GetAcc(float value)
        {
            // 获取加速度值
            return value / 4096.0f; // 直接返回计算后的加速度值
        }
        private static float GetGyr(float value)
        {
            // 获取角速度值
            return value / 16.0f; // 直接返回计算后的角速度值
        }
        private static float[] GetImu(List<float> list, int imuType)
        {
            // 检查list是否为空或null
            if (list == null || list.Count < 3)
            {
                return null;
            }

            // 调用imuRectify方法修正IMU数据
            return ImuRectify(list[0], list[1], list[2], imuType);
        }
        private static float[] ImuRectify(float x, float y, float z, int imuType)
        {
            float[] imu = { x, y, z };

            if (imuType == 1)
            {
                imu = new float[] { -y, x, z };
            }
            else if (imuType == 2)
            {
                imu = new float[] { y, x, z };
            }

            return imu;
        }
        /// <summary>
        /// 获取电池电量。
        /// </summary>
        /// <param name="text">包含电池电量信息的文本数据包。</param>
        /// <returns>电池电量值，如果充电状态无效则返回 -1。</returns>
        public static int GetBattery(string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                throw new ArgumentException("Text data cannot be null or empty.", nameof(text));
            }

            try
            {
                // 提取充电状态
                string hex = text.Substring(RechargeStatusRange[0], RechargeStatusRange[1] - RechargeStatusRange[0]);

                // 提取并转换电量（KWH）
                string kwh = text.Substring(KwhRange[0], KwhRange[1] - KwhRange[0]);
                int x = Convert.ToInt32(kwh, 16); // 将十六进制转换为整数

                // 返回电量，如果充电状态表示无效数据，则返回特定值
                return hex == LtInvalidData ? x : x; // 如果充电状态无效，返回 -1
            }
            catch (ArgumentOutOfRangeException ex)
            {
                throw new ArgumentException("Invalid text data length for battery information extraction.", ex);
            }
            catch (FormatException ex)
            {
                throw new ArgumentException("Invalid hexadecimal format in KWH data.", ex);
            }
        }
        /// <summary>
        /// 检查设备是否被佩戴。
        /// </summary>
        /// <param name="text">包含佩戴状态信息的文本数据包。</param>
        /// <returns>如果设备被佩戴返回 true，否则返回 false。</returns>
        public static bool IsWearPatch(string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                throw new ArgumentException("Text data cannot be null or empty.", nameof(text));
            }

            try
            {
                // 提取佩戴状态
                string hex = text.Substring(LtRange[0], LtRange[1] - LtRange[0]);

                // 返回是否佩戴的状态
                return hex != LtInvalidData; // 如果佩戴状态不是无效数据，则认为设备被佩戴
            }
            catch (ArgumentOutOfRangeException ex)
            {
                throw new ArgumentException("Invalid text data length for wear patch information extraction.", ex);
            }
        }
    }
    /// <summary>
    /// 设备数据
    /// </summary>
    public class DeviceData
    {
        /// <summary>
        /// 存储EEG数据
        /// </summary>
        public List<float> EegList { get; set; }
        /// <summary>
        ///  存储加速度数据
        /// </summary>
        public List<float> AccList { get; set; }
        /// <summary>
        /// 存储角速度数据
        /// </summary>
        public List<float> GyrList { get; set; }
    }
    public class DeviceModel
    {
        /// <summary>
        /// 电量
        /// </summary>
        public int battery { get; set; } = -1;
        /// <summary>
        /// 是否佩戴
        /// </summary>
        public bool wearPatch { get; set; } = false;
        public string DeviceName { get; set; } = null;
        public bool IsDeviceConnect { get; set; } = false;
        public bool IsEegConnect { get; set; } = false;

        // EEG数据池
        public List<float> EegList { get; set; } = new List<float>();

        // 加速度数据池
        public List<float> AccList { get; set; } = new List<float>();

        public AccData AccData { get; set; } = new AccData();

        // 角速度数据池
        public List<float> GyrList { get; set; } = new List<float>();
    }

    public class AccData
    {
        public List<float> AccX { get; set; } = new List<float>();
        public List<float> AccY { get; set; } = new List<float>();
        public List<float> AccZ { get; set; } = new List<float>();
    }
}
